package com.iwhalecloud.bss.kite.cucc.order.util;

import com.google.common.collect.Maps;
import com.iwhalecloud.bss.kite.client.dto.order.OrderCommitRequestDTO;
import com.iwhalecloud.bss.kite.common.constant.KeyConsts;
import com.iwhalecloud.bss.kite.common.constant.ServiceOfferConsts;
import com.iwhalecloud.bss.kite.common.util.KiteListUtils;
import com.iwhalecloud.bss.kite.common.util.KiteStringUtils;
import com.iwhalecloud.bss.kite.cucc.order.bo.scene.SceneInstMergeBO;
import com.iwhalecloud.bss.kite.dataservice.util.SplictUtil;
import com.iwhalecloud.bss.kite.manager.api.IQuerySceneInstService;
import com.iwhalecloud.bss.kite.manager.inst.KiteSceneInst;
import com.iwhalecloud.bss.kite.order.client.dto.OrderRequest;
import com.ztesoft.bss.common.util.SpringUtil;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

/**
 * <Description> <br>
 * 场景实例合并辅助工具类
 *
 * @version 1.0<br>
 * @taskId <br>
 * @CreateDate 2020年3月22日 <br>
 * @since R9.0<br>
 * @see com.iwhalecloud.bss.kite.cucc.order.util <br>
 */
public abstract class SceneInstMergeUtils {

    /**
     * Description: <br>
     * 场景合并计算处理
     *
     * @param request
     * @return <br>
     */
    public static List<OrderRequest> sceneInstsCompute(OrderCommitRequestDTO request) {
        List<OrderRequest> orderRequests = new ArrayList<>();

        List<String> sceneInstIds = request.getSceneInstIds();
        // 1.根据场景实例ID生成顺序排序
        Collections.sort(sceneInstIds);
        Set<String> sceneInstIdSet = new HashSet<>(sceneInstIds);

        // 2.场景实例分组
        IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        List<List<String>> groupIdList = querySceneInstService.groupSceneInsts(sceneInstIdSet, request.getCustId());

        for (List<String> cells : groupIdList) {
            orderRequests.addAll(mergeAll(cells, request));
        }

        return orderRequests;
    }

    /**
     * Description: <br>
     * 场景实例合并
     *
     * @return <br>
     */
    public static List<OrderRequest> mergeAll(List<String> sceneInstIds, OrderCommitRequestDTO request) {
        List<OrderRequest> orderRequests = new ArrayList<>();

        // 获取场景实例对象集合
        List<KiteSceneInst> sceneInstList = getSceneInstList(sceneInstIds, request.getCustId());

        // 场景实例业务依赖互斥分组处理
        List<SceneInstMergeBO> sceneInstMergeBOList = new ArrayList<>();
        if (KiteListUtils.isEmpty(sceneInstList)) {
            return orderRequests;
        }

        if (1 == sceneInstList.size()) {
            getAndCreateSceneInstMergeBO(sceneInstMergeBOList, sceneInstList.get(0), request);
        }
        else {
            for (int i = 0; i < sceneInstList.size() - 1; i++) {
                KiteSceneInst aSceneInst = sceneInstList.get(i);
                SceneInstMergeBO sceneInstMergeBO = getAndCreateSceneInstMergeBO(sceneInstMergeBOList, aSceneInst,
                    request);
                packetSceneInst(sceneInstList, aSceneInst, sceneInstMergeBO, i);
            }

            for (KiteSceneInst sceneInst : sceneInstList) {
                getAndCreateSceneInstMergeBO(sceneInstMergeBOList, sceneInst, request);
            }
        }

        // 生成场景合并后请求对象
        for (SceneInstMergeBO sceneInstMergeBO : sceneInstMergeBOList) {
            orderRequests.add(sceneInstMergeBO.merge(request));
        }

        return orderRequests;
    }

    /**
     * Description: <br>
     * 获取场景实例集合
     *
     * @param sceneInstIds
     * @param custId
     * @return <br>
     */
    public static List<KiteSceneInst> getSceneInstList(List<String> sceneInstIds, String custId) {
        List<KiteSceneInst> sceneInstList = new ArrayList<>();

        IQuerySceneInstService querySceneInstService = SpringUtil.getBean(IQuerySceneInstService.class);
        for (String sceneInstId : sceneInstIds) {
            KiteSceneInst sceneInst = querySceneInstService.getSceneInst(sceneInstId, custId);
            sceneInstList.add(sceneInst);
        }
        return sceneInstList;
    }

    /**
     * Description: <br>
     * 获取和生成场景实例合并业务对象
     *
     * @param sceneInstMergeBOList
     * @param curSceneInst
     * @param request
     * @return <br>
     */
    public static SceneInstMergeBO getAndCreateSceneInstMergeBO(List<SceneInstMergeBO> sceneInstMergeBOList,
        KiteSceneInst curSceneInst, OrderCommitRequestDTO request) {
        SceneInstMergeBO sceneInstMergeBO = null;
        for (SceneInstMergeBO mergeBo : sceneInstMergeBOList) {
            if (mergeBo.contains(curSceneInst)) {
                sceneInstMergeBO = mergeBo;
                break;
            }
        }

        if (Objects.isNull(sceneInstMergeBO)) {
            sceneInstMergeBO = new SceneInstMergeBO(curSceneInst.getCustId());
            sceneInstMergeBO.setCreateStaff(request.getStaffId());
            sceneInstMergeBO.setUpdateStaff(request.getStaffId());
            sceneInstMergeBO.getSceneInstList().add(curSceneInst);
            sceneInstMergeBOList.add(sceneInstMergeBO);
        }

        return sceneInstMergeBO;
    }

    /**
     * Description: <br>
     * 场景实例合并分组打包处理
     *
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @param sceneInstList
     * @param aSceneInst
     * @param sceneInstMergeBO
     * @param idx <br>
     */
    public static void packetSceneInst(List<KiteSceneInst> sceneInstList, KiteSceneInst aSceneInst,
        SceneInstMergeBO sceneInstMergeBO, int idx) {
        for (int j = idx + 1; j < sceneInstList.size(); j++) {
            KiteSceneInst bSceneInst = sceneInstList.get(j);
            if (isCanMerge(aSceneInst, bSceneInst)) {
                if (!sceneInstMergeBO.contains(bSceneInst)) {
                    sceneInstMergeBO.getSceneInstList().add(bSceneInst);
                }
            }
        }
    }

    /**
     * Description: <br>
     * 判断两个业务场景是否能购合并
     *
     * @author xiao.xuzhang<br>
     * @taskId <br>
     * @param aSceneInst
     * @param bSceneInst
     * @return <br>
     */
    public static boolean isCanMerge(KiteSceneInst aSceneInst, KiteSceneInst bSceneInst) {
        boolean flag = false;
        String aServOfferId = aSceneInst.getServiceOfferId();
        String bServOfferId = bSceneInst.getServiceOfferId();
        // 撤单，不做合单处理
        if (KiteStringUtils.equalsAny(KeyConsts.SERVICE_WITHDRAW, aServOfferId, bServOfferId)) {
            return Boolean.FALSE;
        }

        String aOperType = aSceneInst.getOperType();
        String bOperType = bSceneInst.getOperType();
        // 修正，不做合单处理
        if (KiteStringUtils.equalsAny(KeyConsts.KITE_SCENE_INST_OPER_TYPE_1001, aOperType, bOperType)) {
            return Boolean.FALSE;
        }

        // 业务互斥也不做合单处理
        if (SplictUtil.isAllMutex(aServOfferId, bServOfferId)) {
            return Boolean.FALSE;
        }

        // 业务包含
        if (SplictUtil.isEqualOrBigger(aServOfferId, bServOfferId)) {
            return Boolean.TRUE;
        }

        // 两个场景存在新装业务
        if (KiteStringUtils.equalsAny(ServiceOfferConsts.SERVICE_OFFER_ORDER, aServOfferId, bServOfferId)) {
            return Boolean.TRUE;
        }

        // 两个场景存在销售品修改业务
        if (KiteStringUtils.equalsAny(ServiceOfferConsts.SERVICE_OFFER_MODIFY, aServOfferId, bServOfferId)) {
            return Boolean.TRUE;
        }

        // 两个场景存在迁转业务
        if (KiteStringUtils.equalsAny(ServiceOfferConsts.SERVICE_OFFER_FUSION_TRANSFER, aServOfferId, bServOfferId)) {
            return Boolean.TRUE;
        }

        return flag;
    }

    /**
     * Description: <br>
     * 场景实例分组处理，可用于免填单预览等。
     *
     * @taskId <br>
     * @param sceneInstIds
     * @param custId
     * @return <br>
     */
    public static Map<String, List<String>> groupSceneInsts(List<String> sceneInstIds, String custId) {
        Map<String, List<String>> sceneInstMap = Maps.newHashMap();
        OrderCommitRequestDTO request = new OrderCommitRequestDTO();
        request.setSceneInstIds(sceneInstIds);
        request.setCustId(custId);
        request.setPreCheck(true);
        List<OrderRequest> orderRequests = sceneInstsCompute(request);
        for (OrderRequest orderRequest : orderRequests) {
            sceneInstMap.put(orderRequest.getMainSceneInstId(), orderRequest.getSceneInstIds());
        }

        return sceneInstMap;
    }
}
